from Quoridor_game import QuoridorAction, WHITE, BLACK, TIE, QuoridorState, DIRECTIONS
from game_runner import GameRunner
from game_agent import GameAgent
from alpha_beta import AlphaBetaSearch
from alpha_beta_anytime_contract import AlphaBetaAnytimeSearch
import random

from problem import *
from astar import AStar
from time import time
import sys

INFINITY = float('Inf')

class Move(ProblemAction):
	def __init__(self, row, col, nextRow, nextCol):
		self.identity = int(row*1e6 + col*1e4 + nextRow*1e2 + nextCol)
		self.cost = 1;
		
	def __cmp__(self, other):
		return self.identity.__cmp__(other.identity);
	
	def __hash__(self):
		return hash(self.identity);
	
	def __str__(self):
		return str(self.identity)

class Location(ProblemState):
	def __init__(self, row, col, goal, gameState):
		self.row = row;
		self.col = col;
		self.goal = goal; # row number
		self.gameState = gameState;
		
	def getSuccessors(self):
		successors = dict();
		gameState = self.gameState;
		
		for nextRow, nextCol, direction in [(self.row+1, self.col, 'S'), (self.row-1, self.col, 'N'), (self.row, self.col+1, 'E'), (self.row, self.col-1, 'W')]:
			#moves out of board
			if nextRow < 0 or nextRow >= gameState.brdSize or nextCol < 0 or nextCol >= gameState.brdSize:
				continue
			#move illegal because of wall
			if not gameState._moveOkByWalls(direction, nextRow, nextCol):
				continue
			successors[Move(self.row, self.col, nextRow, nextCol)] = Location(nextRow, nextCol, self.goal, self.gameState);
		return successors;
	
	def isGoal(self):
		return (self.row == self.goal);
	
	def __cmp__(self, other):
		if self.row.__cmp__(other.row) != 0:
			return self.row.__cmp__(other.row);
		return self.col.__cmp__(other.col);
	
	def __hash__(self):
		return hash(self.row*100 + self.col);
	
	def __str__(self):
		return "Location: " + str(self.row) + ", " + str(self.col);

# Heuristic for Astar
class Heuristic:
	def __init__(self):
		pass;
		
	def evaluate(self, state):
		return abs(state.goal - state.row);

# Astar
class CompetitionAgent(GameAgent):
	def __init__(self):
		pass
	
	def move(self, game_state):
		action = self.alphaBeta.search(game_state)
		return action
	
	def setup(self, player, game_state, turn_time_limit, setup_time_limit):
		self.player = player
		u = lambda state: self.utility(state)
		self.alphaBeta = AlphaBetaAnytimeSearch(player, turn_time_limit, u)
		self.searchEngine = AStar();

	def utility(self, state):
		winner = state.getWinner()
		if winner is None:
			whiteDistance = 0
			for posW in state.locationsW:
				if posW != None:
					whiteDistance += len(self.searchEngine.find(Location(posW[0], posW[1], state.brdSize - 1, state), Heuristic()));
			
			whiteValue = whiteDistance;
			
			blackDistance = 0
			for posB in state.locationsB:
				if posB != None:
					blackDistance += len(self.searchEngine.find(Location(posB[0], posB[1], 0, state), Heuristic()));
			
			blackValue = blackDistance;
			
			
			utilityValW = blackValue - whiteValue
			
			if self.player == WHITE:
				return utilityValW
			else:
				return -utilityValW			
			
		elif winner == self.player:
			return INFINITY
		elif winner == TIE:
			return 0
		else:
			return -INFINITY



if __name__ == "__main__":
	agents = {}
	agents[WHITE] = CompetitionAgent()
	agents[BLACK] = CompetitionAgent()

	state = QuoridorState(2)
	print 'Initial state: \n'
	print str(state) + '\n' 
	winner = GameRunner(state, agents, 1, 1 ).run()
	print 'Winner:', winner
